import type {
  ButtonProps,
  ButtonState,
  ITabConfig,
  ItemStateConfig,
  IUserCenterModule,
  IUserComponent,
} from '../types/interfaces'
import { Badge } from '../components/badge'
import { withRefreshLoader } from '../components/refresh_loader'
import { BaseModule } from '../lib/abstract'
import { LogStyle } from '../lib/logger'
import { PageHandler } from '../lib/page_handler'
import { ToolKit } from '../lib/utils/toolkit'
import {
  AppStyleCollections,
  BODY_SELECTOR,
  BUILD_CONFIG,
  BUTTON_REFRESH_CLASS,
  BUTTON_STYLES,
  ButtonTexts,
  getAllTitleSelector,
  IS_PRODUCTION,
  ITEM_STATE,
  logger,
  PROJECT_PREFIX,
  STATE_STYLE_MAP,
} from '../types/constants'
import { SYMBOLS } from '../types/interfaces'
import { TimeBadge } from './rank/time_badge'
import { About } from './tab/about'
import { Announcement } from './tab/announcement'
import { Feedback } from './tab/feed_back'
import { Personalization } from './tab/personalization'
import { UtilitySettings } from './tab/utility_settings'

export class UserCenter extends BaseModule implements IUserCenterModule {
  readonly id: string = 'user-center'
  readonly name: string = 'UserCenter'
  readonly isInitialized: boolean = false
  readonly supportedPlatforms?: string[] | undefined

  private readonly pageHandler: PageHandler = PageHandler.getInstance()

  private installTime: Date | undefined
  private announcement: Announcement | undefined
  private utilitySettings: UtilitySettings | undefined
  private personalization: Personalization | undefined
  private feedback: Feedback | undefined
  private about: About | undefined
  private timeBadge: TimeBadge | undefined
  private modeBadge: Badge | undefined
  private component: IUserComponent | undefined
  private readonly modalTitle: string = `${SYMBOLS.USER.DEVELOPER} 用户中心`
  private readonly modalPopupClassName: string = 'user-center-modal'
  private readonly modalContainerClassName: string = 'user-center'
  private readonly modalTitleClassName: string = 'user-center-title'
  private readonly containerSelector: string = `.${this.modalPopupClassName} .${this.modalContainerClassName}`
  private static instance: UserCenter
  private tabConfigs: ITabConfig[] = []

  static async create(): Promise<UserCenter> {
    this.instance = new UserCenter()
    await this.instance.init()
    return this.instance
  }

  async init(): Promise<void> {
    this.announcement = Announcement.getInstance()

    // 『网页增强』需要在『个性化』前，因为『个性化』中的网页主题和样式表依赖『网页增强』的主题同步的记录
    this.utilitySettings = UtilitySettings.getInstance()
    this.personalization = await Personalization.create()

    this.feedback = Feedback.getInstance()
    this.about = About.getInstance()
    this.component = {
      announcement: this.announcement,
      utilitySettings: this.utilitySettings,
      personalization: this.personalization,
      feedback: this.feedback,
      about: this.about,
    }

    this.tabConfigs = [
      {
        id: 'utility',
        name: '网页增强',
        icon: SYMBOLS.OTHERS.ROCKET,
        component: 'utilitySettings',
        buttonBehavior: 'refresh',
      },
      {
        id: 'personalization',
        name: '个性化',
        icon: SYMBOLS.OTHERS.PALETTE,
        component: 'personalization',
        buttonBehavior: 'apply',
        // 这里需要在 personalization 初始化后
        applyHandler: (): Promise<{ success: boolean, invalidCount: number }> => this.applyPersonalization(),
      },
      {
        id: 'feedback',
        name: '意见反馈',
        icon: SYMBOLS.OTHERS.HELP,
        component: 'feedback',
        buttonBehavior: 'open',
        openUrl: BUILD_CONFIG.URL.FEED_BACK_URL,
      },
      {
        id: 'about',
        name: '关于脚本',
        icon: SYMBOLS.UI.HOME,
        component: 'about',
        buttonBehavior: 'hide',
      },
    ]

    // 初始化安装时间
    this.setInstallTime()
    this.installTime = new Date(this.storage.get('install_time', new Date().toLocaleString(), { useDomainIsolation: false, useNamespace: false }))

    // 初始化时间徽章
    this.timeBadge = new TimeBadge(this.installTime)
    // 初始化版本/模式徽章
    this.modeBadge = IS_PRODUCTION
      ? new Badge({
        id: 'version-badge',
        value: `V${BUILD_CONFIG.VERSION}`,
        theme: 'green',
      })
      : new Badge({
        id: 'mode-badge',
        value: '开发模式',
      })
  }

  destroy(): Promise<void> | void {
  }

  core(): Promise<void> | void {
  }

  onToggleCallback(_id: string, _checked: boolean): Promise<void> | void {
  }

  applyConfig(_config: any): void {
  }

  /**
   * 设置安装时间
   */
  private setInstallTime(): void {
    if (!this.storage.get('install_time', undefined, { useDomainIsolation: false, useNamespace: false })) {
      this.storage.set('install_time', new Date().toLocaleString(), { useDomainIsolation: false, useNamespace: false })
    }
  }

  /**
   * 生成用户中心 HTML 内容
   */
  generateHTML(): string {
    const activeTabId = this.getActiveTabId()

    // 生成标签页按钮 HTML
    const tabsHTML = this.tabConfigs.map(tab => `
      <button class="tab ${tab.id === activeTabId ? 'active' : ''}" 
              data-tab="${tab.id}">
        ${tab.icon} ${tab.name}
      </button>
    `).join('')

    // 生成标签页内容 HTML
    const tabContentHTML = this.tabConfigs.map(tab => `
      <div class="tab-pane ${tab.id === activeTabId ? 'active' : ''}" 
        data-tab="${tab.id}">
        ${this.component?.[tab.component].generateHTML()}
      </div>
    `).join('')

    return `
      ${this.component?.announcement.generateHTML()}
      <div class="${this.modalContainerClassName}">
        <div class="${this.modalTitleClassName}">
            <h3>${this.modalTitle}${this.modeBadge?.render()}</h3>
            <div class="stats">
                ${this.timeBadge?.render()}
            </div>
        </div>
        <div class="tab-container">
          <div class="tabs">
            ${tabsHTML}
          </div>
          <div class="tab-content">
            ${tabContentHTML}
          </div>
        </div>
      </div>
    `
  }

  /**
   * 更新按钮行为
   * @param tabId 当前标签页ID
   */
  private updateButtonBehavior(tabId: string): void {
    const tabConfig = this.tabConfigs.find(tab => tab.id === tabId)
    if (!tabConfig)
      return

    const $Button = $(`.${this.modalPopupClassName} .swal2-actions .swal2-confirm`)

    if (!$Button || !$Button.length)
      return

    switch (tabConfig.buttonBehavior) {
      case 'open':
        $Button.css('display', '')
          .text(ButtonTexts.open.normal)
          .off('click')
          .on('click', () => tabConfig.openUrl && ToolKit.browser.url.openNewTab(tabConfig.openUrl))
        break

      case 'refresh':
        $Button.css('display', '')
          .text(ButtonTexts.refresh.normal)
          .addClass(BUTTON_REFRESH_CLASS)
          .off('click')
          .on('click', () => withRefreshLoader())
        break

      case 'save':
        $Button.css('display', '')
          .text(ButtonTexts.save.normal)
          .off('click')
          .on('click', async (e) => {
            e.preventDefault()

            const $target = $(e.currentTarget)

            // 禁用按钮防止重复点击
            this.updateButtonDisabledState($target, true)

            try {
              // 执行保存操作
              await tabConfig.saveHandler?.()
              this.updateButtonUI({
                element: $target,
                props: { type: 'save', isLoading: false },
              }, true)
            }
            catch (error: any) {
              logger.error(ButtonTexts.save.failed, error)
              this.updateButtonUI({
                element: $target,
                props: { type: 'save', isLoading: false },
              }, false)
            }
            return false
          })
        break

      case 'apply':
        $Button.css('display', '')
          .text(ButtonTexts.apply.normal)
          .off('click')
          .on('click', async (e) => {
            e.preventDefault()

            const $target = $(e.currentTarget)

            // 禁用按钮防止重复点击
            this.updateButtonDisabledState($target, true)

            try {
              // 执行保存并获取结果
              const { success, invalidCount } = await tabConfig.applyHandler!()
              // 更新UI状态
              this.updateButtonUI({
                element: $target,
                props: {
                  type: 'apply',
                  isLoading: false,
                  valid: invalidCount === 0,
                  timeout: invalidCount > 0 ? 5000 : 1000,
                },
              }, success)
            }
            catch (error: any) {
              logger.error(ButtonTexts.apply.failed, error)
              this.updateButtonUI({
                element: $target,
                props: { type: 'apply', isLoading: false },
              }, false)
            }
            return false
          })
        break

      case 'hide':
        ToolKit.dom.setElementCssAttribute($Button)
        break
    }
  }

  /**
   * 更新按钮UI状态 （手动更新 UI 反馈而不关闭弹窗）
   * @param state 按钮状态对象
   * @param success 操作是否成功
   * @param timeout 状态恢复时间(ms)
   */
  updateButtonUI(state: ButtonState, success: boolean, timeout: number = 3000): void {
    const { element, props } = state
    const config = ButtonTexts[props.type]

    // 清除之前的定时器
    if (state.timer) {
      clearTimeout(state.timer)
    }

    // 重置按钮基础状态
    this.updateButtonDisabledState(element, false)
    this.resetButtonStyle(element)

    const { className, description } = this.getButtonUIConfig(success, props)
    element.addClass(className).text(description)

    // 设置状态恢复定时器
    state.timer = window.setTimeout(() => {
      this.resetButtonStyle(element).text(config.normal)
      state.timer = undefined
    }, props.timeout ? props.timeout : timeout)
  }

  /**
   * 获取按钮样式（暂未支持 loading）
   * @param success 操作是否成功
   * @param props 按钮属性
   */
  getButtonUIConfig(success: boolean, props: ButtonProps): {
    className: string
    description: string
  } {
    const config = ButtonTexts[props.type]
    if (success) {
      if (config.invalid && props.type === 'apply' && !props.valid) {
        return { className: 'btn-warning', description: config.invalid }
      }
      return { className: 'btn-success', description: config.success }
    }
    else {
      return { className: 'btn-danger', description: config.failed }
    }
  }

  /**
   * 重置按钮状态
   * @param element 按钮元素
   */
  resetButtonStyle(element: JQuery<HTMLElement>): JQuery {
    return element.removeClass('btn-success btn-danger btn-warning btn-loading')
  }

  /**
   * 重置按钮状态
   * @param element 按钮元素
   * @param disabled 是否禁用按钮
   */
  updateButtonDisabledState(element: JQuery<HTMLElement>, disabled: boolean): void {
    element.prop('disabled', disabled)
  }

  /**
   * 获取所有标签页配置
   * @public
   */
  getTabConfigs(): ITabConfig[] {
    return this.tabConfigs
  }

  /**
   * 获取当前激活的标签页 ID （默认激活第一个标签页）
   * @private
   */
  private getActiveTabId(): string {
    return this.tabConfigs[0].id
  }

  /**
   * 设置活动标签页
   * @param activeTab 被激活的标签页元素
   */
  private setActiveTab(activeTab: JQuery<HTMLElement>): void {
    const $container = $('.user-center-modal .user-center .tab-container')
    $container.find('.tab, .tab-pane').removeClass('active')

    // 设置新的活动状态
    activeTab.addClass('active')

    // 显示对应的标签页内容
    const tabId = activeTab.attr('data-tab')
    if (tabId) {
      $container.find(`.tab-content .tab-pane[data-tab="${tabId}"]`).addClass('active')
    }
  }

  /**
   * 初始化标签页切换处理器
   * @param selector 标签容器选择器
   */
  private initTabHandlers(selector: string): void {
    // 初始化按钮行为
    const activeTabId = this.getActiveTabId()
    this.updateButtonBehavior(activeTabId)

    // 使用事件委托处理标签页点击
    $(selector).on('click', (e) => {
      const $tab = $(e.target)
      if (!$tab)
        return

      // 更新活动标签页状态
      this.setActiveTab($tab)

      // 更新按钮行为
      const tabId = $tab.attr('data-tab')
      if (tabId)
        this.updateButtonBehavior(tabId)
    })
  }

  /**
   * 初始化各菜单组件
   */
  private async initComponents(): Promise<void> {
    const initPromises = Object.entries(this.component || {}).map(
      ([name, component]) =>
        this.wrapComponentInit(name, () => component?.handleOpen?.()),
    )

    const results = await Promise.allSettled(initPromises)

    // 分析结果
    const failures = results.filter(r => r.status === 'rejected')
    if (failures.length > 0) {
      logger.warn(`${failures.length}个组件初始化失败，但其他组件已成功加载`)
      failures.forEach((f: PromiseRejectedResult) => {
        logger.error(f.reason)
      })
    }
  }

  /**
   * 包装组件初始化函数，捕获错误并记录
   * @param name 组件名称
   * @param initFn 初始化函数
   */
  private async wrapComponentInit(name: string, initFn: () => Promise<void> | void): Promise<void> {
    try {
      const result = initFn()
      if (result instanceof Promise) {
        await result
      }
      logger.info(`[${this.name}] 菜单 ${name} 加载成功`)
    }
    catch (error: any) {
      logger.error(`[${this.name}] 菜单 ${name} 加载失败:`, error)
      throw error // 仍然抛出错误，但会被allSettled捕获
    }
  }

  /**
   * 处理用户中心打开时的逻辑
   */
  async handleOpen(): Promise<void> {
    const $stats = $('.stats')

    // 绑定徽章事件
    this.timeBadge?.mount($stats)
    this.modeBadge?.mount($stats)

    // 初始化标签页
    this.initTabHandlers(`${this.containerSelector} .tab-container .tabs .tab`)

    await logger.executeWithLogging('加载用户模块', async () => {
      await this.initComponents()
    }, {
      collapsed: true,
      color: LogStyle.groupHeader,
    })
  }

  handleConfirm(): void {

  }

  /**
   * 清空所有个性化状态
   */
  private emptyPersonalizationSaveState(): void {
    this.personalization?.personalizationConfig.forEach((item) => {
      this.storage.delete(`${item.id}${ITEM_STATE.SAVED.suffix}`)
      document.querySelectorAll(`.${this.personalization?.className} .setting-item.render-${item.id}`).forEach((el) => {
        Object.values(ITEM_STATE).forEach((item: ItemStateConfig) => {
          el.classList.remove(item.className)
        })
        el.setAttribute(ITEM_STATE.SAVED.attributes!, 'false')
      })
    })
    logger.important(`[${this.name}] 所有个性化保存状态已清空`)
  }

  /**
   * 显示用户中心弹窗
   * @param initOnly 仅初始化不显示（默认false）
   */
  showDialog(initOnly: boolean = false): void {
    const html = this.generateHTML()

    if (initOnly) {
      ToolKit.serviceAlert.toggleServiceInitAlert(true)

      // 显示服务初始化弹窗
      this.pageHandler.ui.toast.confirm({
        html,
        timer: 5000,
        backdrop: false,
        customClass: {
          popup: this.modalPopupClassName,
          title: this.modalTitleClassName,
          container: AppStyleCollections.Hide.ELEMENT,
        },
        didOpen: async () => {
          await this.handleOpen()
        },
        willClose: () => {
          this.cleanupResources()
          // 移除掉隐藏类，避免影响 SweetAlert2 弹窗后续的自动销毁
          $(`.${this.modalPopupClassName}`)
            .closest('.swal2-container')
            .css('height', '0')
            .removeClass(AppStyleCollections.Hide.ELEMENT)
          ToolKit.serviceAlert.toggleServiceInitAlert(false)
        },
        didClose: () => {
        },
      }).then((_result) => {})
      return
    }

    if (!ToolKit.browser.platform.isScriptSupported()) {
      logger.warn(`[${this.name}] 当前版本不支持当前平台，无法打开用户中心`)
      return
    }

    this.pageHandler.ui.toast.confirm({
      html,
      confirmButtonText: '保存',
      cancelButtonText: '关闭窗口',
      draggable: true, // 允许拖动弹窗
      customClass: {
        popup: this.modalPopupClassName,
        title: this.modalTitleClassName,
      },
      preConfirm: () => {
        return false // 阻止默认的确认关闭行为
      },
      // 弹窗开始打开动画前
      willOpen: () => {
        ToolKit.serviceAlert.toggleServiceInitAlert(false)
        this.emptyPersonalizationSaveState()
      },
      didOpen: async () => {
        await this.handleOpen()
      },
      // 弹窗开始关闭动画前，一般用于移除监听器、清理临时数据
      willClose: () => {
        this.cleanupResources()
      },
      // 弹窗完全关闭且 DOM 移除后，一般用于执行后续逻辑（如刷新页面）
      didClose: () => {
      },
      // 弹窗实例完全销毁后，一般用于终极清理（较少使用）
      didDestroy: () => {
      },
    }).then((result) => {
      if (result.isConfirmed) {
        this.handleConfirm() // 这里不会执行，因为preConfirm返回false阻止了确认关闭（预留）
      }
      // 用户点击了关闭或其他方式关闭弹窗
      else if (result.isDismissed) { /* empty */ }
    })
  }

  /**
   * 应用个性化设置
   */
  async applyPersonalization(): Promise<{ success: boolean, invalidCount: number }> {
    return await this.personalization?.handleSave() || { success: false, invalidCount: 0 }
  }

  /**
   * 清理资源
   */
  private cleanupResources(): void {
    // 1. 清理第三方库实例
    this.timeBadge?.destroy()

    // 2. 移除所有事件监听器
    $(this.containerSelector).off() // 移除容器内所有 jQuery 事件
    document.querySelectorAll(`${this.containerSelector} [data-tab]`).forEach((el) => {
      el.replaceWith(el.cloneNode(true)) // 通过 DOM 克隆移除原生事件
    })

    // 3. 清除动态生成的样式

    // 4. 重置组件状态
    Object.values(this.component || {}).forEach((component) => {
      if (typeof component.destroy === 'function') {
        component.destroy()
      }
    })

    logger.important(`[${this.name}] 已完成弹窗关闭前的资源清理`)
  }

  styles(): string {
    return `
/* 网页功能如果存在刷新生效的徽章则将刷新页面按钮设为危险按钮 */    
${BODY_SELECTOR} .${this.modalPopupClassName}:has(.utility-settings .effect-badge.${STATE_STYLE_MAP.disabled.className}) {
  button.${BUTTON_REFRESH_CLASS} {
    ${BUTTON_STYLES.warning.base}
  }
}

/* ================================= 时间徽章样式 ================================= */
${TimeBadge.styles()}

/* ================================= 主容器样式 ================================= */
.${this.modalPopupClassName} {
  position: relative !important;
  width: 850px !important;
  height: 850px !important;
  
  .${this.modalTitleClassName} {
    position: sticky;
    top: 0;
    left: 50%;
    z-index: 10;
    padding: 10px 0;
    
    h3 {
      position: relative !important;
      display: block !important;
      margin: 20px auto !important;
      font-size: 30px !important;
      text-align: center !important;
      font-weight: 600 !important;
      text-transform: none !important;
    }
    .stats {
      text-align: center;
      color: #666;
      font-size: 12px;
      padding: 2px 8px;
    }
  }
  .swal2-actions {
    position: absolute;
    bottom: 15px;
    left: 50%;
    transform: translateX(-50%);
  }
}

.user-center-modal {
  background: var(--${PROJECT_PREFIX}-theme-bg-base) !important;
  color: var(--${PROJECT_PREFIX}-theme-text-secondary) !important;
  
  ${getAllTitleSelector()} {
    margin: 0px !important; /* 去掉标题所有外边距 */
  }
  
  .user-center {
    position: absolute !important;
    width: 90%;
    height: 50vh !important;
    overflow: visible !important;
    top: 100px;
    left: 50%;
    transform: translateX(-50%) !important;
    
    .menu {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 10px;
      
      .menu-item {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 15px 10px;
        background: #f8f9fa;
        border: none;
        border-radius: 8px;
        cursor: pointer;
        transition: all 0.2s ease;
        
        &:hover {
          background: #e9ecef;
          transform: translateY(-2px);
          box-shadow: 0 4px 8px rgba(0,0,0,0.1);
        }
        
        .icon {
          font-size: 24px;
          margin-bottom: 8px;
        }
        
        span {
          font-size: 14px;
          color: #333;
        }
      }
    }
  }
}

.tab-container {
  height: 100%;
  
  .tabs {
    position: sticky;
    top: 80px; /* 标题高度 + 内边距 */
    z-index: 10;
    padding: 10px 0 0 0;
    margin-bottom: 10px;
    display: flex;
    border-bottom: 1px solid var(--${PROJECT_PREFIX}-theme-code-toolbar-divider) !important;
    
    .tab {
      padding: 8px 15px;
      background: none;
      border: none;
      border-bottom: 2px solid transparent;
      cursor: pointer;
      font-size: 18px;
      transition: all 0.2s ease;
      color: #545454;
      
      &.active {
        border-bottom-color: #4a6bdf;
        color: #4a6bdf;
        font-weight: bold;
      }
      
      &:hover {
        color: #4a6bdf !important;
      }
    }
  }
  
  /* 内容面板样式 */
  .tab-content {
    height: calc(100% - 120px) !important; /* 减去标题和标签页高度 */
    overflow-y: auto;
    ${this.stylesService.scroll.default}
    
    .tab-pane {
      display: none;
      padding: 10px;
      animation: fadeIn 0.3s ease;
      
      &.active {
        display: block;
      }
    }
  }
}
    `
  }
}
